package uk.ac.lkl.common.allocator;




//import java.util.*;

import javax.swing.event.ChangeListener;

import uk.ac.lkl.common.util.ChangeSupport;



/**
 * Needs sub-class so can require clone method.
 * 
 * @author Darren Pearce
 * @version $Revision: 370 $
 * @version $Date: 2007-11-12 14:58:00 +0000 (Mon, 12 Nov 2007) $
 * 
 */
public abstract class ScheduleBlock<T extends ScheduleBlock> implements
        Comparable<ScheduleBlock> {

    private ChangeSupport changeSupport = new ChangeSupport(this);

    private int start;

    private int end;

    private int id;

    private static int NEXT_ID = 0;


    // create an exact copy
    public abstract T createCopy();


    // create an copy but with changed start and end
    public abstract T createCopy(int start, int end);


    public ScheduleBlock(int start,
            int end) {
        if (start <= end)
            setBounds(start, end);
        else
            setBounds(end, start);
        this.id = NEXT_ID++;
    }


    public int getId() {
        return id;
    }


    public int getSize() {
        return end - start + 1;
    }


    public int getStart() {
        return start;
    }


    public int getEnd() {
        return end;
    }


    public void setStart(int start) {
        if (start < 0)
            return;

        if (start == this.start)
            return;

        this.start = start;

        if (start > end)
            end = start;

        fireStateChanged();
    }


    public void setEnd(int end) {
        if (end == this.end)
            return;

        this.end = end;

        if (end < start)
            start = end;

        fireStateChanged();
    }


    public void setBounds(int start, int end) {
        if (start == this.start && end == this.end)
            return;

        this.start = start;
        this.end = end;
        fireStateChanged();
    }


    public void moveStart(int start) {
        move(start - this.start);
    }


    public void move(int movement) {
        setBounds(this.start + movement, this.end + movement);
    }


    public int compareTo(ScheduleBlock other) {
        int startDifference = this.start - other.start;
        if (startDifference != 0)
            return startDifference;

        int sizeDifference = this.getSize() - other.getSize();
        if (sizeDifference != 0)
            return sizeDifference;

        int idDifference = this.getId() - other.getId();
        return idDifference;
    }


    public void addChangeListener(ChangeListener listener) {
        changeSupport.addListener(listener);
    }


    public void removeChangeListener(ChangeListener listener) {
        changeSupport.removeListener(listener);
    }


    private void fireStateChanged() {
        changeSupport.fireStateChanged();
    }


    public String toString() {
        return "[" + id + ": " + start + "-" + end + "]";
    }

}
